package it.softphone.cmc.server.service.impl;

import it.softphone.cmc.server.entity.AttributesEntity;
import it.softphone.cmc.server.entity.TransactionEntity;
import it.softphone.cmc.server.service.QueryTask;
import it.softphone.cmc.server.service.SystemManagerService;
import it.softphone.cmc.server.service.exception.CMCException;
import it.softphone.cmc.shared.entity.Attributes;
import it.softphone.cmc.shared.entity.Transaction;
import it.softphone.commons.exception.NullParameterException;
import it.softphone.commons.json.server.JSONException;
import it.softphone.commons.json.server.JSONObject;
import it.softphone.commons.json.server.JSONUtils;
import it.softphone.commons.service.LogAware;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;


/**
 * 
 * @author softphone
 *
 */
public abstract class GAEEntityManagerServiceImpl extends GAEEntityManagerBaseServiceImpl implements SystemManagerService,LogAware {
	
	@Override
	public Attributes makeAttributes() {
		return new AttributesEntity();
	}


	@Override
	public Attributes makeAttributesFromJson(it.softphone.commons.json.server.JSONObject object) throws JSONException {
		throw new UnsupportedOperationException("makeAttributesFromJson");
		//return new AttributesEntity(object);
	}


	/**
	 * 
	 */
	@Override
	public void createTransaction(final Transaction transaction) throws CMCException {
		
		execTransaction( "createTransaction",  new EMTask<Void>() {

			@Override
			public Void exec(EntityManager em) throws Exception {
				em.persist(transaction);
				em.refresh(transaction);
				return null;
			}
		});
		
	}

	/**
	 * 
	 */
	@Override
	public void storeTransaction(final Transaction transaction) throws CMCException {
		execTransaction("storeTransaction", new EMTask<Void>() {

			@Override
			public Void exec(EntityManager em) throws Exception {
				java.util.Map<String,Object> paramMap = new java.util.HashMap<String,Object>(1);		
				paramMap.put("l_id", transaction.getId());
				
				
				final Transaction t = findSingle( em, "SELECT r FROM TransactionEntity r WHERE r.id = :l_id",  paramMap);
				
				if( t!=null ) {
					em.persist(transaction);
				}
				else {
					final String msg =  String.format("transaction [%d] doesn't exist!", transaction.getId());
					
					throw new CMCException( msg );
				}
				
				return null;
			}
			
		});
	}

	/**
	 * 
	 */
	@SuppressWarnings("unchecked")
	public void findTransactionsByUser(final String userId, final QueryTask<List<TransactionEntity>> task ) throws CMCException {
		if( userId==null ) throw new NullParameterException("userId");
		if( task==null ) throw new NullParameterException("task");

		exec( "findTransactionsByUser", new EMTask<Void>() {

				@Override
				public Void exec(EntityManager em) throws Exception {
					java.util.List<TransactionEntity> result = null;
					
					Query query = em.createQuery( "SELECT r FROM TransactionEntity r WHERE r.userId = :user ");
					
					query.setParameter("user", userId);
					
					result = query.getResultList();
					
					task.run(result);
					return null;
				}
			});
			

		
	}


	/**
	 * 
	 * @param id
	 * @return
	 * @throws CMCException
	 */
	public Transaction findTransactionById(final long id) throws CMCException {
		Transaction result = null;
		
			result = exec( "findTransactionById", new EMTask<Transaction>() {

				@Override
				public Transaction exec(EntityManager em) throws Exception {
					Query query = em.createQuery( "SELECT r FROM TransactionEntity r WHERE r.id = :id ");
					
					query.setParameter("id", id);
					
					return (Transaction) query.getSingleResult();

				}
				
			});
		
		return result;
	}


	@SuppressWarnings("unchecked")
	public void findAllTransactions( final QueryTask<List<Transaction>> task ) throws CMCException {
			if( task==null ) throw new NullParameterException("task");

				exec( "findAllTransactions", new EMTask<Void>()  {

					@Override
					public Void exec(EntityManager em) throws Exception {
						java.util.List<Transaction> result = null;

						Query query = em.createQuery( "SELECT r FROM TransactionEntity r ORDER BY longDate DESC");
						
						result = query.getResultList();
						
						task.run(result);

						return null;
					}
					
				});
						
	}

	@Override
	public Transaction makeTransactionFromJson(JSONObject object) throws JSONException {
		Transaction result = makeTransaction();
		
		JSONUtils.copyTo(result, object);

		return result;
	}


	@Override
	public Transaction makeTransaction() {
		return new TransactionEntity();
	}
	


	

}
